package net.letcode.ct;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.letcode.core.utils.common.DateUtils;
import net.letcode.core.utils.common.StringUtils;
import net.letcode.core.utils.file.FileUtils;
import net.letcode.core.utils.file.PropertyUtils;
import net.letcode.ct.bean.Entity;
import net.letcode.ct.utils.*;

/**
 * 主程序
 * @author zdf
 * @Date 2014年10月26日
 *
 */
public class Main {

	private static String ClassRoot;
	
	/** 生成一对多映射 */
	public static Boolean parseTablePrefix = true;
	
	/** 生成多对一映射 */
	public static Boolean buildManyToOne = false;
	
	/** 生成多对多映射 */
	public static Boolean buildManyToMany = false;
	
	/** 生成一对多映射 */
	public static Boolean buildOneToMany = false;
	
	private static String javaRootFolder;
	private static String mapperRootFolder;
	private static String viewsRootFolder;
	private static String dataBase, packageName, author, version;
	
	/**
	 * 主函数入口
	 * @param args
	 */
	public static void main(String[] args) {

		ClassRoot = FileUtils.getRootClassPath(Main.class);

		//加载配置
		loadProperties();
		
		//读取表名
		Map<String, String> tableMap = CodeUtils.getTableNames(dataBase);
		
		//解析表结构
		List<Entity> entitys = new ArrayList<Entity>();
		Set<String> modules = new HashSet<String>();
		Set<String> tableNames = tableMap.keySet();
		for(String tableName : tableNames)
			entitys.add(CodeUtils.parseEntity(tableName, tableMap.get(tableName), modules, parseTablePrefix));
		
		//解析外键关联
		CodeUtils.parseForeignKey(entitys, dataBase);
		
		//输出文件
		Map<String, Object> data = initDate(modules);
		for(Entity entity : entitys){
			data.put("entity", entity);
			makeFile(entity, data);
		}
	}

	/**
	 * 读取配置文件
	 * @author zdf
	 * @date 2015年7月3日 
	 * @return 目标数据库
	 */
	private static void loadProperties(){
		System.out.println("加载配置文件...");
		PropertyUtils pu = new PropertyUtils();

		pu.load(ClassRoot + "/app.properties");//加载配置文件
		
		//初始化数据库配置
		dataBase = pu.getString("db.database");
		String dbType = pu.getString("db.type");
		String host = pu.getString("db.host");
		Integer port = pu.getInt("db.port");
		String user = pu.getString("db.user");
		String password = pu.getString("db.password");
		
		JdbcUtils.init(host, port, user, password, dataBase, JdbcUtils.DbType.valueOf(dbType));
		
		//初始化SQL
		CodeUtils.SQL_TABLE_NAMES = pu.getString("sql.selectTableNames");
		CodeUtils.SQL_COUNT_PRIMARY_KEY = pu.getString("sql.countPrimaryKey");
		CodeUtils.SQL_TABLE_FIELDS = pu.getString("sql.selectTableFileds");
		CodeUtils.SQL_ALL_FOREIGN_KEY = pu.getString("sql.selectAllForignKey");
		CodeUtils.SQL_MANY_TO_MANY = pu.getString("sql.selectManyToMany");
		
		//初始化代码配置
		parseTablePrefix = pu.getBoolean("db.prefix", true);
		
		packageName = pu.getString("code.packageName");
		author = pu.getString("code.author");
		version = pu.getString("code.version");
		buildManyToOne = pu.getBoolean("code.manyToOne", false);
		buildManyToMany = pu.getBoolean("code.manyToMany", false);
		buildOneToMany = pu.getBoolean("code.oneToMany", false);
	}

	/**
	 * 初始化环境
	 * @author zdf
	 * @date 2015年7月3日
	 * @param modules
	 * @return
	 */
	private static Map<String, Object> initDate(Set<String> modules){
		
		//初始化代码文件目录
		String[] packageNameItem = packageName.split("\\.");
		
		StringBuffer sb = new StringBuffer()
							.append(ClassRoot).append(File.separator)
							.append("sourceCodes").append(File.separator)
							.append("java").append(File.separator);
		
		for(String nameItem : packageNameItem)
			sb.append(nameItem).append(File.separator);
		
		javaRootFolder = sb.toString();
		FileUtils.makeSureFolderExits(javaRootFolder);
		FileUtils.clearFolder(javaRootFolder);

		// mapperFolder
		sb = new StringBuffer()
				.append(ClassRoot).append(File.separator)
				.append("sourceCodes").append(File.separator)
				.append("mapper").append(File.separator);

		mapperRootFolder = sb.toString();
		FileUtils.makeSureFolderExits(mapperRootFolder);
		FileUtils.clearFolder(mapperRootFolder);

		// viewFolder
		sb = new StringBuffer()
				.append(ClassRoot).append(File.separator)
				.append("sourceCodes").append(File.separator)
				.append("views").append(File.separator);
		
		viewsRootFolder = sb.toString();
		FileUtils.makeSureFolderExits(viewsRootFolder);
		FileUtils.clearFolder(viewsRootFolder);
		
		String javaFolderPath, viewFolderPath;
		String moduleName, entityFolder, daoFolder, serviceFolder, serviceImplFolder, webFolder;
		Iterator<String> iterator = modules.iterator();
		while(iterator.hasNext()){
			moduleName = iterator.next();
			
			javaFolderPath = javaRootFolder + moduleName + File.separator;
			entityFolder = javaFolderPath + "entity" + File.separator;
			daoFolder = javaFolderPath + "dao" + File.separator;
			serviceFolder = javaFolderPath + "service" + File.separator;
			serviceImplFolder = serviceFolder + "impl" + File.separator;
			webFolder = javaFolderPath + "web" + File.separator;
			
			FileUtils.makeSureFolderExits(entityFolder);
			FileUtils.makeSureFolderExits(daoFolder);
			FileUtils.makeSureFolderExits(serviceFolder);
			FileUtils.makeSureFolderExits(serviceImplFolder);
			FileUtils.makeSureFolderExits(webFolder);
			
			viewFolderPath = viewsRootFolder + moduleName + File.separator;
			FileUtils.makeSureFolderExits(viewFolderPath);
		}
		
		Map<String, Object> data = new HashMap<String, Object>();
		data.put("author", author);
		data.put("version", version);
		data.put("date", DateUtils.format(new Date(), DateUtils.FORMAT_LONG));
		data.put("packageName", packageName);
		
		return  data;
	}
	
	/**
	 * 生成代码
	 * @author zdf
	 * @date 2015年7月3日
	 * @param entity	实体
	 * @param data	基础信息
	 */
	private static void makeFile(Entity entity, Map<String, Object> data){
		String entityName = entity.getEntityName();
		data.put("entityName", entityName);
		data.put("entityNameLower", StringUtils.firstCharToLowerCase(entityName));
		
		//生成Java代码
		String javaFolderPath = javaRootFolder + File.separator + entity.getModuleName() + File.separator;
		String entityFile = javaFolderPath + "entity" + File.separator + entityName + ".java";
		String daoFile = javaFolderPath + "dao" + File.separator + entityName + "Dao.java";
		String serviceFile = javaFolderPath + "service" + File.separator + entityName + "Service.java";
		String serviceImplFile = javaFolderPath + "service" + File.separator + "impl" + File.separator + entityName + "ServiceImpl.java";
		String controllerFile = javaFolderPath + "web" + File.separator + entityName + "Controller.java";

		FreeMarkerUtils.makeFile(data, "entity.ftl", entityFile);
		FreeMarkerUtils.makeFile(data, "dao.ftl", daoFile);

		FreeMarkerUtils.makeFile(data, "service.ftl", serviceFile);
		FreeMarkerUtils.makeFile(data, "serviceImpl.ftl", serviceImplFile);
		FreeMarkerUtils.makeFile(data, "controller.ftl", controllerFile);

		//生成Mapper
		String mapperFolderPath = mapperRootFolder + File.separator + entity.getModuleName() + File.separator;
		FileUtils.makeSureFolderExits(mapperFolderPath);
		FreeMarkerUtils.makeFile(data, "mapper.ftl", mapperFolderPath + entity.getEntityNameLower() + "Dao.xml");

		//生成Views
		String viewFolderPath = viewsRootFolder + File.separator + entity.getModuleName() + File.separator + entity.getEntityNameLower() + File.separator;
		FileUtils.makeSureFolderExits(viewFolderPath);
		FreeMarkerUtils.makeFile(data, "listView.ftl", viewFolderPath + "list.jsp");
		FreeMarkerUtils.makeFile(data, "formView.ftl", viewFolderPath + "form.jsp");
		
		System.out.println("输出：" + entity.getModuleName() + "." +entityName);
	}
}